#!/usr/bin/env node

const fs = require('fs')
const path = require('path')
const iconv = require('iconv-lite')

// 获取命令行参数
const args = process.argv.slice(2)

if (args.length === 0) {
  console.error('请提供要转换的.dat文件路径或目录路径')
  process.exit(1)
}

const inputPath = args[0]

// 检查路径是否存在
if (!fs.existsSync(inputPath)) {
  console.error(`路径不存在: ${inputPath}`)
  process.exit(1)
}

// 读取文件内容 (使用GBK编码)
function readDatFile(filePath) {
  const buffer = fs.readFileSync(filePath)
  return iconv.decode(buffer, 'gbk')
}

// 解析.dat文件内容
function parseDatContent(content) {
  const entries = []

  // 通过*^分割条目
  const rawEntries = content.split('*^').filter((e) => e.trim())

  for (const rawEntry of rawEntries) {
    try {
      // 查找^#的位置
      const splitIndex = rawEntry.indexOf('^#')
      if (splitIndex === -1) continue

      const englishPart = rawEntry.substring(0, splitIndex)
      const restPart = rawEntry.substring(splitIndex + 2)

      // 解析restPart: 中文内容#开始时间#结束时间#额外信息
      const firstHash = restPart.indexOf('#')
      if (firstHash === -1) continue

      const chinese = restPart.substring(0, firstHash)
      const timeAndExtra = restPart.substring(firstHash + 1)

      // 查找第二个#（开始时间结束）
      const secondHash = timeAndExtra.indexOf('#')
      if (secondHash === -1) continue

      const startTime = timeAndExtra.substring(0, secondHash)
      const endAndExtra = timeAndExtra.substring(secondHash + 1)

      // 查找第三个#（结束时间结束）
      const thirdHash = endAndExtra.indexOf('#')
      let endTime, extra
      if (thirdHash === -1) {
        endTime = endAndExtra
        extra = ''
      } else {
        endTime = endAndExtra.substring(0, thirdHash)
        extra = endAndExtra.substring(thirdHash + 1)
      }

      // 解析英文部分的单词并重组句子
      let cleanEnglish = ''

      // 查找单词：格式为 单词$词根$音标$$$$$ 或 单词$词根$$$$$
      // 使用不同的正则表达式来处理
      const segments = englishPart.split(/\s*\^\s*/).filter((s) => s.trim())
      // 对 a.m. b.m. 的处理
      const willBeRemoved = []
      for (let i = 1; i < segments.length - 1; i++) {
        const previousSeg = segments[i - 1].replaceAll('$', '')
        const currentSeg = segments[i]
        const nextSeg = segments[i + 1].replaceAll('$', '')
        if (previousSeg && currentSeg && nextSeg) {
          if (currentSeg === '.') console.log('englishPart:', englishPart)
          if (currentSeg === '.' && nextSeg.length === 2 && previousSeg.length === 2) {
            segments[i] = previousSeg[0] + currentSeg + nextSeg[0]
            willBeRemoved.push(i - 1)
            willBeRemoved.push(i + 1)
          }
        }
      }
      for (let i = willBeRemoved.length - 1; i >= 0; i--) {
        segments.splice(willBeRemoved[i], 1)
      }

      for (const segment of segments) {
        if (segment.includes('$$$$')) {
          // 有注释的单词
          const parts = segment.split('$$$$')
          const wordPart = parts[0]

          if (wordPart.includes('$')) {
            const wordComponents = wordPart.split('$')
            const word = wordComponents[0]

            if (word.trim()) {
              cleanEnglish += (cleanEnglish ? ' ' : '') + word.trim()
            }
          }
        } else {
          // 没有注释的单词或者标点符号
          const cleanSegment = segment.trim()

          if (cleanSegment) {
            cleanEnglish += (cleanEnglish ? ' ' : '') + cleanSegment
          }
        }
      }
      cleanEnglish = cleanEnglish.replace(/ ,/g, ',')
      cleanEnglish = cleanEnglish.replace(/ \./g, '.')
      cleanEnglish = cleanEnglish.replace(/ \;/g, ';')
      cleanEnglish = cleanEnglish.replace(/ \!/g, '!')
      cleanEnglish = cleanEnglish.replace(/ \?/g, '?')
      // 构建entry对象（只保留指定字段）
      const entry = {
        english: cleanEnglish.trim(),
        chinese: chinese.trim(),
        startTime: parseFloat(startTime),
        endTime: parseFloat(endTime),
      }

      // 查找额外的备注信息
      if (extra && extra.includes('######')) {
        // 备注通常在很多#符号之后
        const notesMatch = extra.match(/([a-zA-Z\u4e00-\u9fa5][^#]*?)#{3,}/)
        if (notesMatch && notesMatch[1].trim()) {
          entry.notes = notesMatch[1].trim()
        }
      }
      // ----------------------------------------
      // 对部分hex的bg2312做进一步处理
      if (entry.chinese.indexOf("'") > -1) {
        const hexBytes = entry.chinese.replace(/\\'([0-9a-fA-F]{2})/g, (match, hex) => {
          return String.fromCharCode(parseInt(hex, 16)) // 转换为字节对应的字符
        })
        // 将字节流转换为 GB2312 编码的中文
        const decodedText = iconv.decode(Buffer.from(hexBytes, 'binary'), 'gbk')
        entry.chinese = decodedText
      }
      if (entry.notes?.indexOf("'") > -1) {
        console.log('notes:', entry.notes)
        const nodesSplit = entry.notes.split("'")
        let hexBytes = ''
        for (let i = 0; i < nodesSplit.length; i++) {
          hexBytes += String.fromCharCode(parseInt(nodesSplit[i], 16))
        }
        // hexBytes = hexBytes.join("");
        console.log('hexBytes:', hexBytes)
        // 将字节流转换为 GB2312 编码的中文
        const decodedText = iconv.decode(Buffer.from(hexBytes, 'binary'), 'gbk')
        console.log('decodedText:', decodedText)
        entry.notes = decodedText
      }
      // ----------------------------------------

      entries.push(entry)
    } catch (e) {
      console.error('解析条目时出错:', e.message)
      continue
    }
  }

  return entries
}

// 转换单个文件
function convertFile(filePath) {
  try {
    const content = readDatFile(filePath)
    const jsonData = parseDatContent(content)

    // 创建输出文件路径
    const jsonFilePath = filePath.replace(/\.dat$/, '.json')

    // 写入JSON文件 (使用UTF-8编码)
    fs.writeFileSync(jsonFilePath, JSON.stringify(jsonData, null, 2), 'utf8')

    console.log(`成功转换文件: ${filePath} -> ${jsonFilePath}`)
    console.log(`  共转换 ${jsonData.length} 条记录`)
    return true
  } catch (error) {
    console.error(`转换文件 ${filePath} 时出错:`, error.message)
    return false
  }
}

// 转换目录下的所有文件
function convertDirectory(dirPath) {
  try {
    const files = fs.readdirSync(dirPath)
    let successCount = 0
    let failCount = 0

    for (const file of files) {
      const filePath = path.join(dirPath, file)
      const stat = fs.statSync(filePath)

      if (stat.isFile() && path.extname(file) === '.dat') {
        if (convertFile(filePath)) {
          successCount++
        } else {
          failCount++
        }
      } else if (stat.isDirectory()) {
        // 递归处理子目录
        const subResults = convertDirectory(filePath)
        successCount += subResults.success
        failCount += subResults.fail
      }
    }

    return { success: successCount, fail: failCount }
  } catch (error) {
    console.error(`遍历目录 ${dirPath} 时出错:`, error.message)
    return { success: 0, fail: 1 }
  }
}

// 主逻辑
try {
  const stat = fs.statSync(inputPath)

  if (stat.isFile()) {
    // 处理单个文件
    if (path.extname(inputPath) === '.dat') {
      if (convertFile(inputPath)) {
        console.log('文件转换完成')
      } else {
        console.error('文件转换失败')
        process.exit(1)
      }
    } else {
      console.error('请提供.dat文件')
      process.exit(1)
    }
  } else if (stat.isDirectory()) {
    // 处理目录
    console.log(`开始转换目录: ${inputPath}`)
    const results = convertDirectory(inputPath)
    console.log(`目录转换完成: 成功 ${results.success} 个文件, 失败 ${results.fail} 个文件`)

    if (results.fail > 0) {
      process.exit(1)
    }
  } else {
    console.error('提供的路径既不是文件也不是目录')
    process.exit(1)
  }
} catch (error) {
  console.error('处理过程中出错:', error.message)
  process.exit(1)
}
